package com.qlm.service.impl;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.jfinal.aop.Before;
import com.jfinal.aop.Enhancer;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.tx.Tx;
import com.jfinal.upload.UploadFile;
import com.qlm.common.Define;
import com.qlm.entity.Order;
import com.qlm.service.ICouponService;
import com.qlm.service.IGiftService;
import com.qlm.tools.Common;
import com.qlm.tools.DateUtils;
import com.qlm.view.CouponView;
import com.qlm.view.ResultMessage;

/**
 * 券码信息接口实现类
 * 
 * @author raoy
 *
 */
public class CouponServiceImpl implements ICouponService {

	protected final static Logger logger = LoggerFactory
			.getLogger(CouponServiceImpl.class);

	public static String COUPON_TABLE_NAME = "t_jf_coupon";
	public static String COUPON_PRIMARY_KEY = "id";

	private IGiftService giftService = Enhancer.enhance(GiftServiceImpl.class);

	@Override
	@Before(Tx.class)
	public ResultMessage saveCoupon(String coupon, String giftID,String pwd) {
		// TODO Auto-generated method stub
		Order couponInfo = new Order();
		if (!couponContains(coupon,giftID)) {
			//保存参数
			couponInfo.set("gift_id", giftID);
			couponInfo.set("coupon", coupon);
			couponInfo.set("pwd", pwd);
			couponInfo.set("status", Define.COUPON_STATUS_UNCLAIMED);
			couponInfo.set("create_time", Common.nowDate());
			// 保存新增券码信息
			boolean result = Db.save(COUPON_TABLE_NAME, COUPON_PRIMARY_KEY,
					couponInfo.toRecord());
			// 更新积分礼品配置信息的数量
			boolean result2 = giftService.updateGiftCount(Define.RM_FAIL, giftID);
			if (result && result2) {
				return ResultMessage.setAllMessage(Define.RM_SUCCESS, "保存券码信息成功。");
			} else {
				return ResultMessage.setAllMessage(Define.RM_FAIL, "该券码保存失败，请检查券码或联系网站管理员。");
			}
		} else {
			return ResultMessage.setAllMessage(Define.RM_FAIL, "该券码已有重复的，请检查后再保存。");
		}
	}

	@SuppressWarnings("unchecked")
	@Override
	@Before(Tx.class)
	public ResultMessage batchSaveCoupon(UploadFile couponFile, String giftID) {
		// TODO Auto-generated method stub
		ResultMessage resultMessage = new ResultMessage();
		File file = couponFile.getFile();
		List<Order> couponList = new ArrayList<Order>();
		if (file == null) {
			return ResultMessage.setAllMessage(Define.RM_FAIL, "上传数据文件失败，请稍后重试或联系网站管理员。");
		}
		String fileName = file.getName();
		// 读取上传文件中的内容
		resultMessage = readFile(giftID, file);
		if(resultMessage.getState() == Define.RM_SUCCESS){//读取文件成功
			couponList = (List<Order>)resultMessage.getData();
		}else{
			return resultMessage;
		}
		// 检查文件名称格式是否正确，检查标题数量和文件中券码的实际数量是否相等
		resultMessage = checkFile(fileName, couponList);
		if (resultMessage.getState() != Define.RM_SUCCESS) {
			return resultMessage;
		}
		// 检查文件内容是否有重复
		resultMessage= couponContainsForBatch(couponList, giftID);
		if(resultMessage.getState() != Define.RM_SUCCESS){
			return resultMessage;
		}		
		// 批量保存券码信息到数据库
		int[] batch2 = batchSave(couponList);
		// 更新积分礼品配置信息的数量
		boolean updateCount = giftService
				.updateGiftCount(batch2.length, giftID);
		if (updateCount && batch2.length == couponList.size()) {
			return ResultMessage.setAllMessage(Define.RM_SUCCESS, "批量添加成功");
		} else {
			return ResultMessage.setAllMessage(Define.RM_FAIL, "批量添加失败,请检查上传文件格式或稍后重试。");
		}
	}

	@Override
	@Before(Tx.class)
	public ResultMessage deleteCoupon(int couponID, String giftID) {
		// TODO Auto-generated method stub
		// 查询该券码是否已经被领取，被领取的不能删除
		Order coupon = Order.Dao.findById(couponID);
		if (coupon.getInt("status") == Define.COUPON_STATUS_RECEIVE) {
			return ResultMessage.setAllMessage(Define.RM_FAIL, "该券码已经被领取，无法删除！");
		}
		// 删除券码信息
		boolean result = Db.deleteById(COUPON_TABLE_NAME, COUPON_PRIMARY_KEY,
				couponID);
		// 修改积分礼品配置中的数量信息
		boolean result2 = giftService.updateGiftCount(-1, giftID);
		if (result && result2) {
			return ResultMessage.setAllMessage(Define.RM_SUCCESS, "删除券码信息成功。");
		} else {
			return ResultMessage.setAllMessage(Define.RM_FAIL, "删除券码信息失败，请联系网站管理员。");
		}
	}

	@Override
	public List<Order> findCouponList() {
		// TODO Auto-generated method stub
		return Order.Dao
				.find("select id,gift_id,coupon,status,create_time,draw_time from "
						+ COUPON_TABLE_NAME);
	}

	@Override
	public Order findCouponByID(int couponID) {
		// TODO Auto-generated method stub
		return Order.Dao.findById(couponID);
	}

	@Override
	public String findCouponByGiftID(String aoData, String giftID) {
		// TODO Auto-generated method stub
		// 将参数转换成jsonArray类型
		JSONArray jsonarray = JSONArray.parseArray(aoData);
		JSONObject obj = (JSONObject) jsonarray.get(0);
		// 传入的查询参数
		String sSearch = obj.get("sSearch").toString();

		StringBuilder sbSql = new StringBuilder(
				"select id,gift_id,coupon,pwd,status,create_time,draw_time from "
						+ COUPON_TABLE_NAME + " where gift_id = '");
		sbSql.append(giftID + "'");
		if (sSearch != null && !"".equals(sSearch)) {
			sbSql.append(" and coupon like  CONCAT('%',");
			sbSql.append("'" + sSearch + "'");
			sbSql.append(",'%') ");
		}
		sbSql.append(" ORDER BY id DESC");

		List<Order> couponList = Order.Dao.find(sbSql.toString());

		List<Object> cvList = new ArrayList<Object>();
		int index = 1;
		for (Order coupon : couponList) {
			CouponView cv = new CouponView();
			cv.setSequenceNumber(index);
			cv.setId(coupon.getInt("id"));
			cv.setCoupon(coupon.getStr("coupon"));
			cv.setPwd(coupon.getStr("pwd"));
			cv.setStatus(coupon.getInt("status"));
			cv.setGiftId(coupon.getInt("gift_id")+"");
			String createTime = DateUtils.formatString(
					coupon.get("create_time"), DateUtils.PATTEN_HMS);
			cv.setCreateTime(createTime);
			String drawTime = DateUtils.formatString(coupon.get("draw_time"),
					DateUtils.PATTEN_HMS);
			cv.setDrawTime(drawTime);
			cvList.add(cv);
			index++;
		}
		return Common.dataTableSearch(aoData, cvList);
	}

	/**
	 * 查询单个券码在数据库中是否重复
	 * 
	 * @param strCoupon
	 * @return false 无重复；true:有重复
	 */
	private static boolean couponContains(String strCoupon,String giftID) {
		Order couponfind = Order.Dao.findFirst(
				"select id,gift_id,coupon,status,create_time,draw_time from "
						+ COUPON_TABLE_NAME + " where gift_id = ? and coupon = ? ",giftID, strCoupon);
		if (couponfind != null) {
			return true;
		}
		return false;
	}

	/**
	 * 查询批量导入的券码是否存在重复,如果有则保存在List中返回
	 * 
	 * @param couponList
	 *            保存Coupon的列表
	 * @param strCoupon
	 *            查询是否重复的Coupon
	 * @return 
	 */
	private static ResultMessage couponContainsForBatch(List<Order> couponList,
			String giftID) {
		List<String> containsList = new ArrayList<String>();

		// 查询该giftID的所有券码
		List<Order> allCoupon = Order.Dao.find(
				"select id,gift_id,coupon,status,create_time,draw_time from "
						+ COUPON_TABLE_NAME + " where gift_id = ?", giftID);
		// 查找输入的文件中数据是否有重复（有问题）
		for (Order coupon : couponList) {
			String code = coupon.get("coupon");
			int icontains = 0;
			for (Order coupon2 : couponList) {
				if (coupon2.get("coupon").equals(code)) {
					icontains++;
				}
			}
			if (icontains > 1) {
				if (!containsList.contains(code)) {
					containsList.add(code);
				}
			}
		}
		// 查找输入的数据和数据库中是否有重复
		for (Order coupon : couponList) {
			String code = coupon.get("coupon");
			for (Order coupon2 : allCoupon) {
				if (coupon2.get("coupon").equals(code)) {
					if (!containsList.contains(code)) {
						containsList.add(code);
					}
				}
			}
		}		
		int allcontains = containsList.size();
		if (allcontains != 0) {//文件内容有重复
			int count = 0;
			StringBuilder sb = new StringBuilder("重复值为:");
			for (String str : containsList) {
				count++;
				if (count != allcontains) {
					sb.append("[" + str + "],");
				} else {
					sb.append("[" + str + "]。");
				}
			}
			return ResultMessage.setAllMessage(Define.RM_FAIL, "批量添加数据中存在重复值" + allcontains
					+ "个，请检查后重试。" + sb.toString());
		}
		return ResultMessage.setAllMessage(Define.RM_SUCCESS, "");
	}

	/**
	 * 批量保存数据到数据库
	 * 
	 * @param list
	 * @return
	 */
	private static int[] batchSave(List<Order> list) {
		// TODO Auto-generated method stub
		if (list == null || list.size() == 0)
			return new int[] { 0 };
		String sql = "insert into "
				+ COUPON_TABLE_NAME
				+ "(gift_id,coupon,status,create_time,draw_time,pwd) values(?,?,?,?,?,?)";
		String columns = "gift_id,coupon,status,create_time,draw_time,pwd";
		int[] result = Db.batch(sql, columns, list, list.size());
		return result;
	}

	/**
	 * 判断字符串是不是数字类型
	 * 
	 * @param str
	 *            被判断的字符串
	 * @return true:是数字；false：不是数字
	 */
	private static boolean isNumeric(String str) {
		Pattern pattern = Pattern.compile("[0-9]*");
		Matcher isNum = pattern.matcher(str);
		if (!isNum.matches()) {
			return false;
		}
		return true;
	}

	/**
	 * 检查文件名称格式是否正确，检查标题数量和文件中券码的实际数量是否相等 判断文件名称是否符合格式：日期_数量；
	 * 示例：20160119_100.txt 如果不符合格式， 提示用户修改文件名，并提示格式和示例。
	 * 
	 * @param fileName
	 *            文件名
	 * @param couponList
	 *            文件中的数据集合
	 * @return
	 */
	private static ResultMessage checkFile(String fileName,
			List<Order> couponList) {
		if (fileName.contains("_")) {//判断文件名称是否含有_
			String[] fileNames = fileName.split("_");
			// 判断文件名称的格式是否正确
			String strNumber = fileNames[1].trim();
			strNumber = strNumber.substring(0, strNumber.indexOf("."));
			// 判断从文件名称中读取的数量是否是数字
			if (isNumeric(strNumber)) {// 是数字
				int number = Integer.parseInt(strNumber);
				int fileNumber = couponList.size();
				if (number != fileNumber) {//判断名称数量和内容的实际数据不相等
					String message = "";					
					int remain_number = number - fileNumber;
					if (remain_number > 0) {
						message = "多了" + remain_number;
					} else {
						remain_number = -remain_number;
						message = "少了" + remain_number;
					}
					return ResultMessage.setAllMessage(Define.RM_FAIL,
							"名称数量比实际数量" + message + "，请修改后再导入。");
				} else {
					return ResultMessage.setAllMessage(Define.RM_SUCCESS, "");
				}
			} else {// 不是数字
				return ResultMessage.setAllMessage(Define.RM_FAIL,
						"导入的文件名中包含的数量不能为非数字类型，正确格式为:日期_数量，示例：20160120_100。");
			}
		} else {
			return ResultMessage.setAllMessage(Define.RM_FAIL,
					"导入的文件名称格式错误，正确格式为:日期_数量，示例：20160120_100。");
		}
	}

	/**
	 * 循环读取上传文件信息，并将信息保存到List中
	 * 
	 * @param giftID
	 * @param file
	 * @return
	 * @throws BusinessAdminException 
	 */
	private static ResultMessage readFile(String giftID, File file){
		List<Order> couponList = new ArrayList<Order>();
		BufferedReader br = null;
		// 循环读取文件中的
		try {
			String data = "";
			br = new BufferedReader(new FileReader(file));
			while (null != (data = br.readLine())) {
				String couponCode = data.trim();
				if (!"".equals(couponCode)) {//剔除空行
					Order coupon = new Order();
					String[] arr = couponCode.split(",");//判断是否有密码
					if(arr.length==2){
						coupon.set("pwd", arr[arr.length-1]);
					}
					coupon.set("coupon", arr[0]);
					coupon.set("gift_id", giftID);
					coupon.set("status", Define.COUPON_STATUS_UNCLAIMED);
					coupon.set("create_time", Common.nowDate());
					couponList.add(coupon);
				}
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			logger.error(e.getMessage(), e);
			return ResultMessage.setAllMessage(Define.RM_FAIL, "读取批量上传文件失败，请重试或联系网站管理员");
		} finally {
			try {
				if (br != null) {
					br.close();
				}
				file.delete();//读完后删除存放在服务器临时文件夹中的文件
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				logger.error(e.getMessage(), e);
				return ResultMessage.setAllMessage(Define.RM_FAIL, "读取批量上传文件失败，请重试或联系网站管理员");
			}
		}
		return ResultMessage.setAllMessage(Define.RM_SUCCESS, "读取批量上传文件成功", couponList);
	}
}
